<template>
  <div class="roles">
    <!-- 1、面包屑导航  -->
    <el-breadcrumb :separator-icon="ArrowRight">
      <el-breadcrumb-item :to="{ path: '/home' }">首页</el-breadcrumb-item>
      <el-breadcrumb-item>角色管理</el-breadcrumb-item>
      <el-breadcrumb-item>角色列表</el-breadcrumb-item>
    </el-breadcrumb>
    <!-- 2.卡片 -->
    <el-card>
      <!-- 2-1 添加角色 -->
      <el-row>
        <el-col :span="2">
          <el-button
            :icon="Plus"
            type="primary"
            @click="addDialogVisible = true"
            >添加角色</el-button
          >
        </el-col>
      </el-row>
      <!-- 2-2 角色列表 -->
      <el-table
        :data="tableData.roles"
        border
        stripe
        fit
        :header-cell-style="header_cell_style"
        style="width: 100%"
      >
        <el-table-column type="expand" label="展开" width="80" align="center">
          <template #default="props">
            <el-row
              v-for="(item1, index1) in props.row.children"
              :key="item1.id"
              :class="['bd-bottom', index1 == 0 ? 'bd-top' : '']"
            >
              <el-col :span="5" class="r1">
                <el-tag
                  size="large"
                  effect="dark"
                  closable
                  @close="deleteRights(props.row, item1)"
                  >{{ item1.authName }}</el-tag
                >
                <el-icon><CaretRight /></el-icon>
              </el-col>
              <el-col :span="19">
                <el-row
                  v-for="(item2, index2) in item1.children"
                  :key="item2.id"
                  :class="index2 !== 0 ? 'bd-top' : ''"
                >
                  <el-col :span="5" class="r2">
                    <el-tag
                      size="large"
                      effect="dark"
                      closable
                      type="success"
                      @close="deleteRights(props.row, item2)"
                      >{{ item2.authName }}</el-tag
                    >
                    <el-icon><CaretRight /></el-icon>
                  </el-col>
                  <el-col :span="19">
                    <el-tag
                      size="large"
                      type="warning"
                      effect="dark"
                      closable
                      class="r3"
                      @close="deleteRights(props.row, item3)"
                      v-for="item3 in item2.children"
                      :key="item3.id"
                      >{{ item3.authName }}</el-tag
                    >
                  </el-col>
                </el-row>
              </el-col>
            </el-row>
          </template>
        </el-table-column>
        <el-table-column type="index" label="序号" width="80" align="center" />
        <el-table-column prop="roleName" label="角色名称" align="center" />
        <el-table-column prop="roleDesc" label="角色描述" align="center" />
        <el-table-column label="操作" align="center" width="350">
          <template #default="scope">
            <el-button
              type="primary"
              :icon="EditPen"
              size="default"
              @click="showUpdate(scope.row)"
              >修改</el-button
            >
            <el-button
              type="danger"
              :icon="Delete"
              size="default"
              @click="deleteRole(scope.row)"
              >删除</el-button
            >
            <el-button
              type="success"
              :icon="Setting"
              size="default"
              @click="showGranteDialog(scope.row)"
              >设置权限</el-button
            >
          </template>
        </el-table-column>
      </el-table>
      <!-- 2-3 分页器 -->
      <el-pagination
        :currentPage="pagenum"
        :page-size="pagesize"
        :page-sizes="[5, 10, 15, 20, 25, 30, 35, 40, 45, 50]"
        background
        layout="total, sizes, prev, pager, next, jumper"
        :total="total"
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
      />
    </el-card>
    <!-- 3、分配权限对话框 -->
    <el-dialog
      v-model="granteRightsDialogVisible"
      title="分配权限"
      width="50%"
      draggable
    >
      <el-tree
        ref="elTreeRef"
        :data="elTreeData"
        show-checkbox
        node-key="id"
        :default-checked-keys="default_checked_keys"
        :props="defaultProps"
        default-expand-all
      />
   
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="granteRights">确认</el-button>
          <el-button type="primary" @click="granteRightsDialogVisible = false"
            >取消</el-button
          >
        </span>
      </template>
    </el-dialog>

    <!-- 4、添加角色对话框 -->
    <el-dialog
      v-model="addDialogVisible"
      title="添加角色"
      width="50%"
      draggable
      @close="reset(addRef)"
    >
      <el-form
        ref="addRef"
        :model="addForm"
        :rules="rules"
        label-width="80px"
        size="large"
      >
        <el-form-item label="角色名称" prop="roleName">
          <el-input v-model="addForm.roleName" />
        </el-form-item>
        <el-form-item label="角色描述" prop="roleDesc">
          <el-input v-model="addForm.roleDesc" />
        </el-form-item>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="submitAdd(addRef)">确认</el-button>
          <el-button type="primary" @click="addDialogVisible = false"
            >取消</el-button
          >
        </span>
      </template>
    </el-dialog>

    <!-- 5、修改对话框 -->
    <el-dialog
      v-model="updateDialogVisible"
      title="修改角色"
      width="50%"
      draggable
      @close="reset(updateRef)"
    >
      <el-form
        ref="updateRef"
        :model="updateForm"
        :rules="rules"
        label-width="80px"
        size="large"
      >
        <el-form-item label="角色名称" prop="roleName">
          <el-input v-model="updateForm.roleName" />
        </el-form-item>
        <el-form-item label="角色描述" prop="roleDesc">
          <el-input v-model="updateForm.roleDesc" />
        </el-form-item>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="submitUpdate(updateRef)">修改</el-button>
          <el-button type="primary" @click="updateDialogVisible = false"
            >取消</el-button
          >
        </span>
      </template>
    </el-dialog>
  </div>
</template>

<script setup>
/*---------------------- 引入资源 ---------------------- */
import { ref, reactive, onMounted, computed } from "vue";
import {
  ArrowRight,
  Plus,
  EditPen,
  Delete,
  Setting,
  CaretRight,
} from "@element-plus/icons-vue";
import { error, success, confirm, info } from "@/utils/message";
import request from "@/utils/request";

/*---------------------- 定义变量 ---------------------- */
let roleList = ref([]), //所有的角色的列表
  total = ref(0), // 角色的总数
  pagenum = ref(1), // 当前页码
  pagesize = ref(5), // 一页几条
  roleId = ref(0), // 分配权限对应的角色id
  tableData = reactive({
    // 通过计算属性获得角色分页数据
    roles: computed(() => {
      let arr = roleList.value,
        start = (pagenum.value - 1) * pagesize.value,
        end = start + pagesize.value;
      if (end > arr.length) {
        end = arr.length;
      }
      return arr.slice(start, end);
    }),
  }), // 角色表格绑定的数据源
  header_cell_style = ref({
    backgroundColor: "#00A0ff",
    color: "#fff",
    textAlign: "center",
  }), // 表格头部的单元格样式
  granteRightsDialogVisible = ref(false), // 分配权限对话框是否显示
  elTreeRef = ref(), //el-tree绑定的ref属性
  elTreeData = ref([]), //el-tree绑定的数据源
  defaultProps = {
    children: "children",
    label: "authName",
  }, // el-tree的默认配置
  default_checked_keys = ref([]), // el-tree绑定的默认选中的checkbox对应的id数组
  addDialogVisible = ref(false), // 控制添加对话框是否显示
  addRef = ref(null),
  addForm = reactive({
    roleName: "",
    roleDesc: "",
  }),
  rules = reactive({
    roleName: [
      { required: true, message: "输入角色名称", trigger: "blur" },
      { min: 3, max: 15, message: "角色名称3-15字符", trigger: "blur" },
    ],
    roleDesc: [
      { required: true, message: "输入角色描述", trigger: "blur" },
      { min: 3, max: 50, message: "角色描述长度3-50字符", trigger: "blur" },
    ],
  }),
  updateDialogVisible = ref(false), // 控制修改对话框是否显示
  updateRef = ref(),
  updateForm = reactive({
    id: 0,
    roleName: "",
    roleDesc: "",
  });

/*---------------------- 功能函数 ---------------------- */
// 删除角色的信息
function deleteRole(role) {
  confirm("确定要永久删除吗？", "删除角色", {
    confirmButtonText: "确认",
    cancelButtonText: "取消",
    type: "warning",
  })
    .then(async () => {
      //点击确定后执行的函数
      let option = {
        url: `roles/${role.id}`,
        type: "delete",
      };
      try {
        let { data: res } = await request(option);
        if (res.meta.status !== 200) {
          return error(res.meta.msg);
        }
        success(res.meta.msg);
        if (pagenum.value !== 1 && roleList.value.length === 1) {
          pagenum.value--;
        }
        getRolesList();
      } catch (err) {
        console.log(err);
      }
    })
    .catch(() => {
      //点击取消后执行的函数
      info("您取消了删除");
    });
}
//显示修改对话框
function showUpdate(role) {
  for (const key in updateForm) {
    updateForm[key] = role[key];
  }
  updateDialogVisible.value = true;
}
// 执行修改角色操作
async function updateRole() {
  let option = {
    url: `roles/${updateForm.id}`,
    type: "put",
    data: updateForm,
  };
  try {
    let { data: res } = await request(option);
    if (res.meta.status !== 200) {
      return error(res.meta.msg);
    }
    success(res.meta.msg);
    updateDialogVisible.value = false;
    getRolesList();
  } catch (error) {
    console.log(error);
  }
}
// 提交修改表单
function submitUpdate(form) {
  form.validate((v) => {
    if (!v) {
      return error("请正确填写信息");
    }
    updateRole();
  });
}
//添加角色
async function addRole() {
  let option = {
    url: "roles",
    type: "post",
    data: addForm,
  };
  try {
    let { data: res } = await request(option);
    if (res.meta.status !== 201) {
      return error(res.meta.msg);
    }
    success(res.meta.msg);
    addDialogVisible.value = false;
    getRightList();
  } catch (error) {
    console.log(error);
  }
}
// 提交添加表单
function submitAdd(form) {
  form.validate((v) => {
    if (!v) {
      return error("请正确填写信息");
    }
    addRole();
  });
}
// 添加表单重置
function reset(form) {
  form.resetFields();
}
// 分配权限函数
async function granteRights() {
  // 获得所有tree选中的权限的id
  let rids = [
    ...elTreeRef.value.getHalfCheckedKeys(),
    ...elTreeRef.value.getCheckedKeys(),
  ];
  // 判断当前的tree有没有选中权限
  if (rids.length === 0) {
    return error("请选择角色的权限");
  }
  rids = rids.join(",");
  // 提交修改操作
  let option = {
    url: `roles/${roleId.value}/rights`,
    type: "post",
    data: { rids },
  };
  try {
    let { data: res } = await request(option);
    if (res.meta.status !== 200) {
      return error(res.meta.msg);
    }
    success(res.meta.msg);
    granteRightsDialogVisible.value = false;
    getRolesList();
  } catch (error) {
    console.log(error);
  }
}
//获得角色对象的所有三级权限的id存入default_checked_keys数组
function getRoleL3Rights(role) {
  if (!role.children) {
    return default_checked_keys.value.push(role.id);
  }
  role.children.forEach((element) => {
    getRoleL3Rights(element);
  });
}
// 获得所有的权限的树状列表
async function getRightList() {
  let option = {
    url: "rights/tree",
    type: "get",
  };
  try {
    let { data: res } = await request(option);
    if (res.meta.status !== 200) {
      return error(res.meta.msg);
    }
    elTreeData.value = res.data;
  } catch (error) {
    console.log(error);
  }
}
//显示分配角色对话框
async function showGranteDialog(role) {
  roleId.value = role.id;
  // 请求所有的权限列表
  await getRightList();
  // 保存当前角色的所有三级权限的id数组到default_checked_keys
  default_checked_keys.value = [];
  getRoleL3Rights(role);
  // 修改对话框的可见性
  granteRightsDialogVisible.value = true;
}
//删除角色的权限
function deleteRights(role, rights) {
  confirm("确定要删除当前角色权限吗？", "删除权限", {
    confirmButtonText: "确认",
    cancelButtonText: "取消",
    type: "warning",
  })
    .then(async () => {
      //点击确定后执行的函数
      let option = {
        url: `roles/${role.id}/rights/${rights.id}`,
        type: "delete",
      };
      try {
        let { data: res } = await request(option);
        if (res.meta.status !== 200) {
          return error(res.meta.msg);
        }
        success(res.meta.msg);
        //删除成功的返回值是修改后的角色对应的权限列表
        role.children = res.data;
      } catch (err) {
        console.log(err);
      }
    })
    .catch(() => {
      //点击取消后执行的函数
      info("您取消了删除");
    });
}
// 一页几条发生变化执行的操作
function handleSizeChange(size) {
  pagesize.value = size;
  pagenum.value=1
  getRolesList();
}
// 页码发生变化时执行的操作
function handleCurrentChange(num) {
  pagenum.value = num;
  getRolesList();
}
// 获得所有的角色列表
async function getRolesList() {
  let option = {
    url: "roles",
    type: "get",
  };
  try {
    let { data: res } = await request(option);
    if (res.meta.status !== 200) {
      return error(res.meta.msg);
    }
    roleList.value = res.data;
    total.value = res.data.length;
  } catch (error) {
    console.log(error);
  }
}
/*---------------------- 生命周期函数 ---------------------- */
onMounted(() => {
  getRolesList();
});
</script>

<style lang="scss" scoped>
.el-card {
  margin: 10px 0;
}
.el-table {
  margin: 20px 0;
}
.el-pagination {
  float: right;
  margin-bottom: 15px;
}
.bd-bottom {
  border-bottom: 1px solid rgba($color: #000, $alpha: 0.1);
}
.bd-top {
  border-top: 1px solid rgba($color: #000, $alpha: 0.1);
}
.el-row {
  padding: 5px 0;
  .r1 {
    display: flex;
    align-items: center;
    justify-content: center;
  }
  .r2 {
    display: flex;
    align-items: center;
  }
  .r3 {
    margin: 5px;
  }
}
</style>